//package com.ruitu.arad.support.view;
//
//import android.content.Context;
//import android.database.DataSetObserver;
//import android.graphics.Canvas;
//import android.graphics.Rect;
//import android.graphics.drawable.Drawable;
//import android.os.Parcel;
//import android.os.Parcelable;
//import android.os.SystemClock;
//import android.support.v4.os.ParcelableCompat;
//import android.support.v4.os.ParcelableCompatCreatorCallbacks;
//import android.support.v4.view.KeyEventCompat;
//import android.support.v4.view.MotionEventCompat;
//import android.support.v4.view.PagerAdapter;
//import android.support.v4.view.VelocityTrackerCompat;
//import android.support.v4.view.ViewCompat;
//import android.support.v4.view.ViewConfigurationCompat;
//import android.support.v4.widget.EdgeEffectCompat;
//import android.util.AttributeSet;
//import android.util.Log;
//import android.view.FocusFinder;
//import android.view.KeyEvent;
//import android.view.MotionEvent;
//import android.view.SoundEffectConstants;
//import android.view.VelocityTracker;
//import android.view.View;
//import android.view.ViewConfiguration;
//import android.view.ViewGroup;
//import android.view.ViewParent;
//import android.view.accessibility.AccessibilityEvent;
//import android.view.animation.Interpolator;
//import android.widget.Scroller;
//
//import java.util.ArrayList;
//import java.util.Collections;
//import java.util.Comparator;
//
//
///**
// * 不缓存的ViewPager
// * <p>
// * Created by Shuwen on 2016年7月9日10:03:57
// */
//
//public class NoCacheViewPager extends NoScrollViewPager {
//    private static final String TAG = "LazyViewPager";
//    private static final boolean DEBUG = false;
//    private static final boolean USE_CACHE = false;
//    private static final int DEFAULT_OFFSCREEN_PAGES = 0;// 默认的加载页面,ViewPager是1个,所以会加载两个Fragment
//    private static final int MAX_SETTLE_DURATION = 600; // ms
//
//    static class ItemInfo {
//        Object object;
//        int position;
//        boolean scrolling;
//    }
//
//    private static final Comparator<ItemInfo> COMPARATOR = new Comparator<ItemInfo>() {
//
//        @Override
//
//        public int compare(ItemInfo lhs, ItemInfo rhs) {
//            return lhs.position - rhs.position;
//        }
//
//    };
//
//
//    private static final Interpolator sInterpolator = new Interpolator() {
//
//        public float getInterpolation(float t) {
//            // _o(t) = t * t * ((tension + 1) * t + tension)
//            // o(t) = _o(t - 1) + 1
//            t -= 1.0f;
//            return t * t * t + 1.0f;
//        }
//
//    };
//
//    private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
//    private PagerAdapter mAdapter;
//    private int mCurItem; // Index of currently displayed page.
//    private int mRestoredCurItem = -1;
//    private Parcelable mRestoredAdapterState = null;
//    private ClassLoader mRestoredClassLoader = null;
//    private Scroller mScroller;
//    private PagerObserver mObserver;
//
//    private int mPageMargin;
//    private Drawable mMarginDrawable;
//    private int mChildWidthMeasureSpec;
//    private int mChildHeightMeasureSpec;
//    private boolean mInLayout;
//    private boolean mScrollingCacheEnabled;
//    private boolean mPopulatePending;
//    private boolean mScrolling;
//    private int mOffscreenPageLimit = DEFAULT_OFFSCREEN_PAGES;
//    private boolean mIsBeingDragged;
//    private boolean mIsUnableToDrag;
//    private int mTouchSlop;
//    private float mInitialMotionX;
//
//    /**
//     * Position of the last motion event.
//     */
//    private float mLastMotionX;
//    private float mLastMotionY;
//
//    /**
//     * ID of the active pointer. This is used to retain consistency during
//     * <p>
//     * drags/flings if multiple pointers are used.
//     */
//    private int mActivePointerId = INVALID_POINTER;
//
//    /**
//     * Sentinel value for no current active pointer. Used by
//     * <p>
//     * {@link #mActivePointerId}.
//     */
//    private static final int INVALID_POINTER = -1;
//
//    /**
//     * Determines speed during touch scrolling
//     */
//    private VelocityTracker mVelocityTracker;
//    private int mMinimumVelocity;
//    private int mMaximumVelocity;
//    private float mBaseLineFlingVelocity;
//    private float mFlingVelocityInfluence;
//    private boolean mFakeDragging;
//    private long mFakeDragBeginTime;
//    private EdgeEffectCompat mLeftEdge;
//    private EdgeEffectCompat mRightEdge;
//    private boolean mFirstLayout = true;
//    private OnPageChangeListener mOnPageChangeListener;
//
//    /**
//     * Indicates that the pager is in an idle, settled state. The current page
//     * <p>
//     * is fully in view and no animation is in progress.
//     */
//    public static final int SCROLL_STATE_IDLE = 0;
//
//    /**
//     * Indicates that the pager is currently being dragged by the user.
//     */
//    public static final int SCROLL_STATE_DRAGGING = 1;
//
//    /**
//     * Indicates that the pager is in the process of settling to a final
//     * <p>
//     * position.
//     */
//    public static final int SCROLL_STATE_SETTLING = 2;
//    private int mScrollState = SCROLL_STATE_IDLE;
//
//    /**
//     * Callback interface for responding to changing state of the selected page.
//     */
//    public interface OnPageChangeListener {
//
//        /**
//         * This method will be invoked when the current page is scrolled, either
//         * <p>
//         * as part of a programmatically initiated smooth scroll or a user
//         * <p>
//         * initiated touch scroll.
//         *
//         * @param position             Position index of the first page currently being
//         *                             <p>
//         *                             displayed. Page position+1 will be visible if
//         *                             <p>
//         *                             positionOffset is nonzero.
//         * @param positionOffset       Value from [0, 1) indicating the offset from the page at
//         *                             <p>
//         *                             position.
//         * @param positionOffsetPixels Value in pixels indicating the offset from position.
//         */
//        public void onPageScrolled(int position, float positionOffset,
//                                   int positionOffsetPixels);
//
//
//        /**
//         * This method will be invoked when a new page becomes selected.
//         * <p>
//         * Animation is not necessarily complete.
//         *
//         * @param position Position index of the new selected page.
//         */
//        public void onPageSelected(int position);
//
//
//        /**
//         * Called when the scroll state changes. Useful for discovering when the
//         * <p>
//         * user begins dragging, when the pager is automatically settling to the
//         * <p>
//         * current page, or when it is fully stopped/idle.
//         *
//         * @param state The new scroll state.
//         * @see android.support.v4.view.ViewPager#SCROLL_STATE_IDLE
//         * @see android.support.v4.view.ViewPager#SCROLL_STATE_DRAGGING
//         * @see android.support.v4.view.ViewPager#SCROLL_STATE_SETTLING
//         */
//        public void onPageScrollStateChanged(int state);
//
//    }
//
//
//    /**
//     * Simple implementation of the
//     * <p>
//     * interface with stub implementations of each method. Extend this if you do
//     * <p>
//     * not intend to override every method of
//     */
//    public static class SimpleOnPageChangeListener implements
//            OnPageChangeListener {
//        @Override
//        public void onPageScrolled(int position, float positionOffset,
//                                   int positionOffsetPixels) {
//            // This space for rent
//        }
//
//        @Override
//        public void onPageSelected(int position) {
//            // This space for rent
//        }
//
//        @Override
//        public void onPageScrollStateChanged(int state) {
//            // This space for rent
//        }
//
//    }
//
//
//    public NoCacheViewPager(Context context) {
//        super(context);
//        initViewPager();
//    }
//
//
//    public NoCacheViewPager(Context context, AttributeSet attrs) {
//        super(context, attrs);
//        initViewPager();
//    }
//
//
//    void initViewPager() {
//        setWillNotDraw(false);
//        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
//        setFocusable(true);
//        final Context context = getContext();
//        mScroller = new Scroller(context, sInterpolator);
//        final ViewConfiguration configuration = ViewConfiguration.get(context);
//        mTouchSlop = ViewConfigurationCompat
//                .getScaledPagingTouchSlop(configuration);
//        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
//        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
//        mLeftEdge = new EdgeEffectCompat(context);
//        mRightEdge = new EdgeEffectCompat(context);
//
//        float density = context.getResources().getDisplayMetrics().density;
//        mBaseLineFlingVelocity = 2500.0f * density;
//        mFlingVelocityInfluence = 0.4f;
//    }
//
//
//    private void setScrollState(int newState) {
//        if (mScrollState == newState) {
//            return;
//        }
//
//        mScrollState = newState;
//        if (mOnPageChangeListener != null) {
//            mOnPageChangeListener.onPageScrollStateChanged(newState);
//        }
//
//    }
//
//    public void setAdapter(PagerAdapter adapter) {
//        if (mAdapter != null) {
//            mAdapter.unregisterDataSetObserver(mObserver);
//            mAdapter.startUpdate(this);
//            for (int i = 0; i < mItems.size(); i++) {
//                final ItemInfo ii = mItems.get(i);
//                mAdapter.destroyItem(this, ii.position, ii.object);
//            }
//
//            mAdapter.finishUpdate(this);
//            mItems.clear();
//            removeAllViews();
//            mCurItem = 0;
//            scrollTo(0, 0);
//
//        }
//
//        mAdapter = adapter;
//        if (mAdapter != null) {
//            if (mObserver == null) {
//                mObserver = new PagerObserver();
//            }
//            mAdapter.registerDataSetObserver(mObserver);
//            mPopulatePending = false;
//            if (mRestoredCurItem >= 0) {
//                mAdapter.restoreState(mRestoredAdapterState,
//                        mRestoredClassLoader);
//                setCurrentItemInternal(mRestoredCurItem, false, true);
//                mRestoredCurItem = -1;
//                mRestoredAdapterState = null;
//                mRestoredClassLoader = null;
//            } else {
//                populate();
//            }
//
//        }
//
//    }
//
//
//    public PagerAdapter getAdapter() {
//
//        return mAdapter;
//    }
//
//
//    /**
//     * Set the currently selected page. If the ViewPager has already been
//     * <p>
//     * through its first layout there will be a smooth animated transition
//     * <p>
//     * between the current item and the specified item.
//     *
//     * @param item Item index to select
//     */
//    public void setCurrentItem(int item) {
//        mPopulatePending = false;
//        setCurrentItemInternal(item, !mFirstLayout, false);
//    }
//
//    /**
//     * Set the currently selected page.
//     *
//     * @param item         Item index to select
//     * @param smoothScroll True to smoothly scroll to the new item, false to transition
//     *                     <p>
//     *                     immediately
//     */
//    public void setCurrentItem(int item, boolean smoothScroll) {
//        mPopulatePending = false;
//        setCurrentItemInternal(item, smoothScroll, false);
//
//    }
//
//
//    public int getCurrentItem() {
//        return mCurItem;
//    }
//
//    void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {
//        setCurrentItemInternal(item, smoothScroll, always, 0);
//    }
//
//    void setCurrentItemInternal(int item, boolean smoothScroll, boolean always,
//                                int velocity) {
//        if (mAdapter == null || mAdapter.getCount() <= 0) {
//            setScrollingCacheEnabled(false);
//            return;
//        }
//        if (!always && mCurItem == item && mItems.size() != 0) {
//            setScrollingCacheEnabled(false);
//            return;
//        }
//
//        if (item < 0) {
//            item = 0;
//        } else if (item >= mAdapter.getCount()) {
//            item = mAdapter.getCount() - 1;
//        }
//
//        final int pageLimit = mOffscreenPageLimit;
//        if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
//            // We are doing a jump by more than one page. To avoid
//            // glitches, we want to keep all current pages in the view
//            // until the scroll ends.
//            for (int i = 0; i < mItems.size(); i++) {
//                mItems.get(i).scrolling = true;
//            }
//        }
//
//        final boolean dispatchSelected = mCurItem != item;
//        mCurItem = item;
//        populate();
//        final int destX = (getWidth() + mPageMargin) * item;
//        if (smoothScroll) {
//            smoothScrollTo(destX, 0, velocity);
//            if (dispatchSelected && mOnPageChangeListener != null) {
//                mOnPageChangeListener.onPageSelected(item);
//            }
//        } else {
//            if (dispatchSelected && mOnPageChangeListener != null) {
//                mOnPageChangeListener.onPageSelected(item);
//            }
//            completeScroll();
//            scrollTo(destX, 0);
//        }
//
//    }
//
//    public void setOnPageChangeListener(OnPageChangeListener listener) {
//        mOnPageChangeListener = listener;
//    }
//
//    /**
//     * Returns the number of pages that will be retained to either side of the
//     * <p>
//     * current page in the view hierarchy in an idle state. Defaults to 1.
//     *
//     * @return How many pages will be kept offscreen on either side
//     * @see #setOffscreenPageLimit(int)
//     */
//    public int getOffscreenPageLimit() {
//        return mOffscreenPageLimit;
//    }
//
//    /**
//     * Set the number of pages that should be retained to either side of the
//     * <p>
//     * current page in the view hierarchy in an idle state. Pages beyond this
//     * <p>
//     * limit will be recreated from the adapter when needed.
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * This is offered as an optimization. If you know in advance the number of
//     * <p>
//     * pages you will need to support or have lazy-loading mechanisms in place
//     * <p>
//     * on your pages, tweaking this setting can have benefits in perceived
//     * <p>
//     * smoothness of paging animations and interaction. If you have a small
//     * <p>
//     * number of pages (3-4) that you can keep active all at once, less time
//     * <p>
//     * will be spent in layout for newly created view subtrees as the user pages
//     * <p>
//     * back and forth.
//     * <p>
//     * </p>
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * You should keep this limit low, especially if your pages have complex
//     * <p>
//     * layouts. This setting defaults to 1.
//     * <p>
//     * </p>
//     *
//     * @param limit How many pages will be kept offscreen in an idle state.
//     */
//    public void setOffscreenPageLimit(int limit) {
//        if (limit < DEFAULT_OFFSCREEN_PAGES) {
//            Log.w(TAG, "Requested offscreen page limit " + limit
//                    + " too small; defaulting to " + DEFAULT_OFFSCREEN_PAGES);
//            limit = DEFAULT_OFFSCREEN_PAGES;
//        }
//
//        if (limit != mOffscreenPageLimit) {
//            mOffscreenPageLimit = limit;
//            populate();
//        }
//
//    }
//
//
//    /**
//     * Set the margin between pages.
//     *
//     * @param marginPixels Distance between adjacent pages in pixels
//     * @see #getPageMargin()
//     * @see #setPageMarginDrawable(Drawable)
//     * @see #setPageMarginDrawable(int)
//     */
//    public void setPageMargin(int marginPixels) {
//        final int oldMargin = mPageMargin;
//        mPageMargin = marginPixels;
//        final int width = getWidth();
//        recomputeScrollPosition(width, width, marginPixels, oldMargin);
//        requestLayout();
//    }
//
//
//    /**
//     * Return the margin between pages.
//     *
//     * @return The size of the margin in pixels
//     */
//    public int getPageMargin() {
//        return mPageMargin;
//    }
//
//    /**
//     * Set a drawable that will be used to fill the margin between pages.
//     *
//     * @param d Drawable to display between pages
//     */
//    public void setPageMarginDrawable(Drawable d) {
//        mMarginDrawable = d;
//        if (d != null)
//            refreshDrawableState();
//        setWillNotDraw(d == null);
//        invalidate();
//
//    }
//
//
//    /**
//     * Set a drawable that will be used to fill the margin between pages.
//     *
//     * @param resId Resource ID of a drawable to display between pages
//     */
//    public void setPageMarginDrawable(int resId) {
//        setPageMarginDrawable(getContext().getResources().getDrawable(resId));
//    }
//
//    @Override
//    protected boolean verifyDrawable(Drawable who) {
//        return super.verifyDrawable(who) || who == mMarginDrawable;
//    }
//
//
//    @Override
//    protected void drawableStateChanged() {
//        super.drawableStateChanged();
//        final Drawable d = mMarginDrawable;
//        if (d != null && d.isStateful()) {
//            d.setState(getDrawableState());
//        }
//    }
//
//
//    // We want the duration of the page snap animation to be influenced by the
//    // distance that
//    // the screen has to travel, however, we don't want this duration to be
//    // effected in a
//    // purely linear fashion. Instead, we use this method to moderate the effect
//    // that the distance
//    // of travel has on the overall snap duration.
//    float distanceInfluenceForSnapDuration(float f) {
//        f -= 0.5f; // center the values about 0.
//        f *= 0.3f * Math.PI / 2.0f;
//        return (float) Math.sin(f);
//
//    }
//
//
//    /**
//     * Like {@link View#scrollBy}, but scroll smoothly instead of
//     * <p>
//     * immediately.
//     *
//     * @param x the number of pixels to scroll by on the X axis
//     * @param y the number of pixels to scroll by on the Y axis
//     */
//    void smoothScrollTo(int x, int y) {
//        smoothScrollTo(x, y, 0);
//    }
//
//    /**
//     * Like {@link View#scrollBy}, but scroll smoothly instead of
//     * <p>
//     * immediately.
//     *
//     * @param x        the number of pixels to scroll by on the X axis
//     * @param y        the number of pixels to scroll by on the Y axis
//     * @param velocity the velocity associated with a fling, if applicable. (0
//     *                 <p>
//     *                 otherwise)
//     */
//    void smoothScrollTo(int x, int y, int velocity) {
//        if (getChildCount() == 0) {
//            // Nothing to do.
//            setScrollingCacheEnabled(false);
//            return;
//        }
//
//        int sx = getScrollX();
//        int sy = getScrollY();
//        int dx = x - sx;
//        int dy = y - sy;
//        if (dx == 0 && dy == 0) {
//            completeScroll();
//            setScrollState(SCROLL_STATE_IDLE);
//            return;
//        }
//
//        setScrollingCacheEnabled(true);
//        mScrolling = true;
//        setScrollState(SCROLL_STATE_SETTLING);
//        final float pageDelta = (float) Math.abs(dx)
//                / (getWidth() + mPageMargin);
//        int duration = (int) (pageDelta * 100);
//        velocity = Math.abs(velocity);
//        if (velocity > 0) {
//            duration += (duration / (velocity / mBaseLineFlingVelocity))
//                    * mFlingVelocityInfluence;
//        } else {
//            duration += 100;
//        }
//
//        duration = Math.min(duration, MAX_SETTLE_DURATION);
//        mScroller.startScroll(sx, sy, dx, dy, duration);
//        invalidate();
//    }
//
//
//    void addNewItem(int position, int index) {
//
//        ItemInfo ii = new ItemInfo();
//        ii.position = position;
//        ii.object = mAdapter.instantiateItem(this, position);
//        if (index < 0) {
//            mItems.add(ii);
//        } else {
//            mItems.add(index, ii);
//        }
//
//    }
//
//    void dataSetChanged() {
//        // This method only gets called if our observer is attached, so mAdapter
//        // is non-null.
//        boolean needPopulate = mItems.size() < 3
//                && mItems.size() < mAdapter.getCount();
//        int newCurrItem = -1;
//        for (int i = 0; i < mItems.size(); i++) {
//            final ItemInfo ii = mItems.get(i);
//            final int newPos = mAdapter.getItemPosition(ii.object);
//            if (newPos == PagerAdapter.POSITION_UNCHANGED) {
//                continue;
//            }
//
//            if (newPos == PagerAdapter.POSITION_NONE) {
//                mItems.remove(i);
//                i--;
//                mAdapter.destroyItem(this, ii.position, ii.object);
//                needPopulate = true;
//                if (mCurItem == ii.position) {
//                    // Keep the current item in the valid range
//                    newCurrItem = Math.max(0,
//                            Math.min(mCurItem, mAdapter.getCount() - 1));
//                }
//                continue;
//            }
//
//
//            if (ii.position != newPos) {
//
//                if (ii.position == mCurItem) {
//
//                    // Our current item changed position. Follow it.
//
//                    newCurrItem = newPos;
//
//                }
//
//
//                ii.position = newPos;
//
//                needPopulate = true;
//
//            }
//
//        }
//
//
//        Collections.sort(mItems, COMPARATOR);
//
//
//        if (newCurrItem >= 0) {
//
//            // TODO This currently causes a jump.
//
//            setCurrentItemInternal(newCurrItem, false, true);
//
//            needPopulate = true;
//
//        }
//
//        if (needPopulate) {
//
//            populate();
//
//            requestLayout();
//
//        }
//
//    }
//
//
//    void populate() {
//
//        if (mAdapter == null) {
//
//            return;
//
//        }
//
//
//        // Bail now if we are waiting to populate. This is to hold off
//
//        // on creating views from the time the user releases their finger to
//
//        // fling to a new position until we have finished the scroll to
//
//        // that position, avoiding glitches from happening at that point.
//
//        if (mPopulatePending) {
//
//            if (DEBUG)
//
//                Log.i(TAG, "populate is pending, skipping for now...");
//
//            return;
//
//        }
//
//
//        // Also, don't populate until we are attached to a window. This is to
//
//        // avoid trying to populate before we have restored our view hierarchy
//
//        // state and conflicting with what is restored.
//
//        if (getWindowToken() == null) {
//
//            return;
//
//        }
//
//
//        mAdapter.startUpdate(this);
//
//
//        final int pageLimit = mOffscreenPageLimit;
//
//        final int startPos = Math.max(0, mCurItem - pageLimit);
//
//        final int N = mAdapter.getCount();
//
//        final int endPos = Math.min(N - 1, mCurItem + pageLimit);
//
//
//        if (DEBUG)
//
//            Log.v(TAG, "populating: startPos=" + startPos + " endPos=" + endPos);
//
//
//        // Add and remove pages in the existing list.
//
//        int lastPos = -1;
//
//        for (int i = 0; i < mItems.size(); i++) {
//
//            ItemInfo ii = mItems.get(i);
//
//            if ((ii.position < startPos || ii.position > endPos)
//
//                    && !ii.scrolling) {
//
//                if (DEBUG)
//
//                    Log.i(TAG, "removing: " + ii.position + " @ " + i);
//
//                mItems.remove(i);
//
//                i--;
//
//                mAdapter.destroyItem(this, ii.position, ii.object);
//
//            } else if (lastPos < endPos && ii.position > startPos) {
//
//                // The next item is outside of our range, but we have a gap
//
//                // between it and the last item where we want to have a page
//
//                // shown. Fill in the gap.
//
//                lastPos++;
//
//                if (lastPos < startPos) {
//
//                    lastPos = startPos;
//
//                }
//
//                while (lastPos <= endPos && lastPos < ii.position) {
//
//                    if (DEBUG)
//
//                        Log.i(TAG, "inserting: " + lastPos + " @ " + i);
//
//                    addNewItem(lastPos, i);
//
//                    lastPos++;
//
//                    i++;
//
//                }
//
//            }
//
//            lastPos = ii.position;
//
//        }
//
//
//        // Add any new pages we need at the end.
//
//        lastPos = mItems.size() > 0 ? mItems.get(mItems.size() - 1).position
//
//                : -1;
//
//        if (lastPos < endPos) {
//
//            lastPos++;
//
//            lastPos = lastPos > startPos ? lastPos : startPos;
//
//            while (lastPos <= endPos) {
//
//                if (DEBUG)
//
//                    Log.i(TAG, "appending: " + lastPos);
//
//                addNewItem(lastPos, -1);
//
//                lastPos++;
//
//            }
//
//        }
//
//
//        if (DEBUG) {
//
//            Log.i(TAG, "Current page list:");
//
//            for (int i = 0; i < mItems.size(); i++) {
//
//                Log.i(TAG, "#" + i + ": page " + mItems.get(i).position);
//
//            }
//
//        }
//
//
//        ItemInfo curItem = null;
//
//        for (int i = 0; i < mItems.size(); i++) {
//
//            if (mItems.get(i).position == mCurItem) {
//
//                curItem = mItems.get(i);
//
//                break;
//
//            }
//
//        }
//
//        mAdapter.setPrimaryItem(this, mCurItem,
//
//                curItem != null ? curItem.object : null);
//
//
//        mAdapter.finishUpdate(this);
//
//
//        if (hasFocus()) {
//
//            View currentFocused = findFocus();
//
//            ItemInfo ii = currentFocused != null ? infoForAnyChild(currentFocused)
//
//                    : null;
//
//            if (ii == null || ii.position != mCurItem) {
//
//                for (int i = 0; i < getChildCount(); i++) {
//
//                    View child = getChildAt(i);
//
//                    ii = infoForChild(child);
//
//                    if (ii != null && ii.position == mCurItem) {
//
//                        if (child.requestFocus(FOCUS_FORWARD)) {
//
//                            break;
//
//                        }
//
//                    }
//
//                }
//
//            }
//
//        }
//
//    }
//
//
//    public static class SavedState extends View.BaseSavedState {
//
//        int position;
//
//        Parcelable adapterState;
//
//        ClassLoader loader;
//
//
//        public SavedState(Parcelable superState) {
//
//            super(superState);
//
//        }
//
//
//        @Override
//
//        public void writeToParcel(Parcel out, int flags) {
//
//            super.writeToParcel(out, flags);
//
//            out.writeInt(position);
//
//            out.writeParcelable(adapterState, flags);
//
//        }
//
//
//        @Override
//
//        public String toString() {
//
//            return "FragmentPager.SavedState{"
//
//                    + Integer.toHexString(System.identityHashCode(this))
//
//                    + " position=" + position + "}";
//
//        }
//
//
//        public static final Creator<SavedState> CREATOR = ParcelableCompat
//
//                .newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {
//
//                    @Override
//
//                    public SavedState createFromParcel(Parcel in,
//
//                                                       ClassLoader loader) {
//
//                        return new SavedState(in, loader);
//
//                    }
//
//
//                    @Override
//
//                    public SavedState[] newArray(int size) {
//
//                        return new SavedState[size];
//
//                    }
//
//                });
//
//
//        SavedState(Parcel in, ClassLoader loader) {
//
//            super(in);
//
//            if (loader == null) {
//
//                loader = getClass().getClassLoader();
//
//            }
//
//            position = in.readInt();
//
//            adapterState = in.readParcelable(loader);
//
//            this.loader = loader;
//
//        }
//
//    }
//
//
//    @Override
//
//    public Parcelable onSaveInstanceState() {
//
//        Parcelable superState = super.onSaveInstanceState();
//
//        SavedState ss = new SavedState(superState);
//
//        ss.position = mCurItem;
//
//        if (mAdapter != null) {
//
//            ss.adapterState = mAdapter.saveState();
//
//        }
//
//        return ss;
//
//    }
//
//
//    @Override
//
//    public void onRestoreInstanceState(Parcelable state) {
//
//        if (!(state instanceof SavedState)) {
//
//            super.onRestoreInstanceState(state);
//
//            return;
//
//        }
//
//
//        SavedState ss = (SavedState) state;
//
//        super.onRestoreInstanceState(ss.getSuperState());
//
//
//        if (mAdapter != null) {
//
//            mAdapter.restoreState(ss.adapterState, ss.loader);
//
//            setCurrentItemInternal(ss.position, false, true);
//
//        } else {
//
//            mRestoredCurItem = ss.position;
//
//            mRestoredAdapterState = ss.adapterState;
//
//            mRestoredClassLoader = ss.loader;
//
//        }
//
//    }
//
//    @Override
//    public void addView(View child, int index, ViewGroup.LayoutParams params) {
//        if (mInLayout) {
//            addViewInLayout(child, index, params);
//            child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec);
//        } else {
//            super.addView(child, index, params);
//        }
//        if (USE_CACHE) {
//            if (child.getVisibility() != GONE) {
//                child.setDrawingCacheEnabled(mScrollingCacheEnabled);
//            } else {
//                child.setDrawingCacheEnabled(false);
//            }
//        }
//    }
//
//    ItemInfo infoForChild(View child) {
//        for (int i = 0; i < mItems.size(); i++) {
//            ItemInfo ii = mItems.get(i);
//            if (mAdapter.isViewFromObject(child, ii.object)) {
//                return ii;
//            }
//        }
//        return null;
//    }
//
//    ItemInfo infoForAnyChild(View child) {
//        ViewParent parent;
//        while ((parent = child.getParent()) != this) {
//            if (parent == null || !(parent instanceof View)) {
//                return null;
//            }
//            child = (View) parent;
//        }
//        return infoForChild(child);
//
//    }
//
//
//    @Override
//
//    protected void onAttachedToWindow() {
//
//        super.onAttachedToWindow();
//
//        mFirstLayout = true;
//
//    }
//
//
//    @Override
//
//    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//
//        // For simple implementation, or internal size is always 0.
//
//        // We depend on the container to specify the layout size of
//
//        // our view. We can't really know what it is since we will be
//
//        // adding and removing different arbitrary views and do not
//
//        // want the layout to change as this happens.
//
//        setMeasuredDimension(getDefaultSize(0, widthMeasureSpec),
//
//                getDefaultSize(0, heightMeasureSpec));
//
//
//        // Children are just made to fill our space.
//
//        mChildWidthMeasureSpec = View.MeasureSpec.makeMeasureSpec(getMeasuredWidth()
//
//                - getPaddingLeft() - getPaddingRight(), View.MeasureSpec.EXACTLY);
//
//        mChildHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
//
//                getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
//
//                View.MeasureSpec.EXACTLY);
//
//
//        // Make sure we have created all fragments that we need to have shown.
//
//        mInLayout = true;
//
//        populate();
//
//        mInLayout = false;
//
//
//        // Make sure all children have been properly measured.
//
//        final int size = getChildCount();
//
//        for (int i = 0; i < size; ++i) {
//
//            final View child = getChildAt(i);
//
//            if (child.getVisibility() != GONE) {
//
//                if (DEBUG)
//
//                    Log.v(TAG, "Measuring #" + i + " " + child + ": "
//
//                            + mChildWidthMeasureSpec);
//
//                child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec);
//
//            }
//
//        }
//
//    }
//
//
//    @Override
//
//    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//
//        super.onSizeChanged(w, h, oldw, oldh);
//
//
//        // Make sure scroll position is set correctly.
//
//        if (w != oldw) {
//
//            recomputeScrollPosition(w, oldw, mPageMargin, mPageMargin);
//
//        }
//
//    }
//
//
//    private void recomputeScrollPosition(int width, int oldWidth, int margin,
//
//                                         int oldMargin) {
//
//        final int widthWithMargin = width + margin;
//
//        if (oldWidth > 0) {
//
//            final int oldScrollPos = getScrollX();
//
//            final int oldwwm = oldWidth + oldMargin;
//
//            final int oldScrollItem = oldScrollPos / oldwwm;
//
//            final float scrollOffset = (float) (oldScrollPos % oldwwm) / oldwwm;
//
//            final int scrollPos = (int) ((oldScrollItem + scrollOffset) * widthWithMargin);
//
//            scrollTo(scrollPos, getScrollY());
//
//            if (!mScroller.isFinished()) {
//
//                // We now return to your regularly scheduled scroll, already in
//
//                // progress.
//
//                final int newDuration = mScroller.getDuration()
//
//                        - mScroller.timePassed();
//
//                mScroller.startScroll(scrollPos, 0, mCurItem * widthWithMargin,
//
//                        0, newDuration);
//
//            }
//
//        } else {
//
//            int scrollPos = mCurItem * widthWithMargin;
//
//            if (scrollPos != getScrollX()) {
//
//                completeScroll();
//
//                scrollTo(scrollPos, getScrollY());
//
//            }
//
//        }
//
//    }
//
//
//    @Override
//
//    protected void onLayout(boolean changed, int l, int t, int r, int b) {
//
//        mInLayout = true;
//
//        populate();
//
//        mInLayout = false;
//
//
//        final int count = getChildCount();
//
//        final int width = r - l;
//
//
//        for (int i = 0; i < count; i++) {
//
//            View child = getChildAt(i);
//
//            ItemInfo ii;
//
//            if (child.getVisibility() != GONE
//
//                    && (ii = infoForChild(child)) != null) {
//
//                int loff = (width + mPageMargin) * ii.position;
//
//                int childLeft = getPaddingLeft() + loff;
//
//                int childTop = getPaddingTop();
//
//                if (DEBUG)
//
//                    Log.v(TAG,
//
//                            "Positioning #" + i + " " + child + " f="
//
//                                    + ii.object + ":" + childLeft + ","
//
//                                    + childTop + " " + child.getMeasuredWidth()
//
//                                    + "x" + child.getMeasuredHeight());
//
//                child.layout(childLeft, childTop,
//
//                        childLeft + child.getMeasuredWidth(),
//
//                        childTop + child.getMeasuredHeight());
//
//            }
//
//        }
//
//        mFirstLayout = false;
//
//    }
//
//
//    @Override
//
//    public void computeScroll() {
//
//        if (DEBUG)
//
//            Log.i(TAG, "computeScroll: finished=" + mScroller.isFinished());
//
//        if (!mScroller.isFinished()) {
//
//            if (mScroller.computeScrollOffset()) {
//
//                if (DEBUG)
//
//                    Log.i(TAG, "computeScroll: still scrolling");
//
//                int oldX = getScrollX();
//
//                int oldY = getScrollY();
//
//                int x = mScroller.getCurrX();
//
//                int y = mScroller.getCurrY();
//
//
//                if (oldX != x || oldY != y) {
//
//                    scrollTo(x, y);
//
//                }
//
//
//                if (mOnPageChangeListener != null) {
//
//                    final int widthWithMargin = getWidth() + mPageMargin;
//
//                    final int position = x / widthWithMargin;
//
//                    final int offsetPixels = x % widthWithMargin;
//
//                    final float offset = (float) offsetPixels / widthWithMargin;
//
//                    mOnPageChangeListener.onPageScrolled(position, offset,
//
//                            offsetPixels);
//
//                }
//
//
//                // Keep on drawing until the animation has finished.
//
//                invalidate();
//
//                return;
//
//            }
//
//        }
//
//
//        // Done with scroll, clean up state.
//
//        completeScroll();
//
//    }
//
//
//    private void completeScroll() {
//
//        boolean needPopulate = mScrolling;
//
//        if (needPopulate) {
//
//            // Done with scroll, no longer want to cache view drawing.
//
//            setScrollingCacheEnabled(false);
//
//            mScroller.abortAnimation();
//
//            int oldX = getScrollX();
//
//            int oldY = getScrollY();
//
//            int x = mScroller.getCurrX();
//
//            int y = mScroller.getCurrY();
//
//            if (oldX != x || oldY != y) {
//
//                scrollTo(x, y);
//
//            }
//
//            setScrollState(SCROLL_STATE_IDLE);
//
//        }
//
//        mPopulatePending = false;
//
//        mScrolling = false;
//
//        for (int i = 0; i < mItems.size(); i++) {
//
//            ItemInfo ii = mItems.get(i);
//
//            if (ii.scrolling) {
//
//                needPopulate = true;
//
//                ii.scrolling = false;
//
//            }
//
//        }
//
//        if (needPopulate) {
//
//            populate();
//
//        }
//
//    }
//
//
//    @Override
//    public boolean onInterceptTouchEvent(MotionEvent ev) {
//        /*
//         * This method JUST determines whether we want to intercept the motion.
//         * If we return true, onMotionEvent will be called and we do the actual
//         * scrolling there.
//         */
//        final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
//        // Always take care of the touch gesture being complete.
//        if (action == MotionEvent.ACTION_CANCEL
//                || action == MotionEvent.ACTION_UP) {
//            // Release the drag.
//            if (DEBUG)
//                Log.v(TAG, "Intercept done!");
//            mIsBeingDragged = false;
//            mIsUnableToDrag = false;
//            mActivePointerId = INVALID_POINTER;
//            return false;
//
//        }
//
//
//        // Nothing more to do here if we have decided whether or not we
//
//        // are dragging.
//
//        if (action != MotionEvent.ACTION_DOWN) {
//
//            if (mIsBeingDragged) {
//
//                if (DEBUG)
//
//                    Log.v(TAG, "Intercept returning true!");
//
//                return true;
//
//            }
//
//            if (mIsUnableToDrag) {
//
//                if (DEBUG)
//
//                    Log.v(TAG, "Intercept returning false!");
//
//                return false;
//
//            }
//
//        }
//
//
//        switch (action) {
//
//            case MotionEvent.ACTION_MOVE: {
//
//                /*
//
//                 * mIsBeingDragged == false, otherwise the shortcut would have
//
//                 * caught it. Check whether the user has moved far enough from his
//
//                 * original down touch.
//
//                 */
//
//
//
//                /*
//
//                 * Locally do absolute value. mLastMotionY is set to the y value of
//
//                 * the down event.
//
//                 */
//
//                final int activePointerId = mActivePointerId;
//
//                if (activePointerId == INVALID_POINTER) {
//
//                    // If we don't have a valid id, the touch down wasn't on
//
//                    // content.
//
//                    break;
//
//                }
//
//
//                final int pointerIndex = MotionEventCompat.findPointerIndex(ev,
//
//                        activePointerId);
//
//                final float x = MotionEventCompat.getX(ev, pointerIndex);
//
//                final float dx = x - mLastMotionX;
//
//                final float xDiff = Math.abs(dx);
//
//                final float y = MotionEventCompat.getY(ev, pointerIndex);
//
//                final float yDiff = Math.abs(y - mLastMotionY);
//
//                final int scrollX = getScrollX();
//
//                final boolean atEdge = (dx > 0 && scrollX == 0)
//
//                        || (dx < 0 && mAdapter != null && scrollX >= (mAdapter
//
//                        .getCount() - 1) * getWidth() - 1);
//
//                if (DEBUG)
//
//                    Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + ","
//
//                            + yDiff);
//
//
//                if (canScroll(this, false, (int) dx, (int) x, (int) y)) {
//
//                    // Nested view has scrollable area under this point. Let it be
//
//                    // handled there.
//
//                    mInitialMotionX = mLastMotionX = x;
//
//                    mLastMotionY = y;
//
//                    return false;
//
//                }
//
//                if (xDiff > mTouchSlop && xDiff > yDiff) {
//
//                    if (DEBUG)
//
//                        Log.v(TAG, "Starting drag!");
//
//                    mIsBeingDragged = true;
//
//                    setScrollState(SCROLL_STATE_DRAGGING);
//
//                    mLastMotionX = x;
//
//                    setScrollingCacheEnabled(true);
//
//                } else {
//
//                    if (yDiff > mTouchSlop) {
//
//                        // The finger has moved enough in the vertical
//
//                        // direction to be counted as a drag... abort
//
//                        // any attempt to drag horizontally, to work correctly
//
//                        // with children that have scrolling containers.
//
//                        if (DEBUG)
//
//                            Log.v(TAG, "Starting unable to drag!");
//
//                        mIsUnableToDrag = true;
//
//                    }
//
//                }
//
//                break;
//
//            }
//
//
//            case MotionEvent.ACTION_DOWN: {
//
//                /*
//
//                 * Remember location of down touch. ACTION_DOWN always refers to
//
//                 * pointer index 0.
//
//                 */
//
//                mLastMotionX = mInitialMotionX = ev.getX();
//
//                mLastMotionY = ev.getY();
//
//                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
//
//
//                if (mScrollState == SCROLL_STATE_SETTLING) {
//
//                    // Let the user 'catch' the pager as it animates.
//
//                    mIsBeingDragged = true;
//
//                    mIsUnableToDrag = false;
//
//                    setScrollState(SCROLL_STATE_DRAGGING);
//
//                } else {
//
//                    completeScroll();
//
//                    mIsBeingDragged = false;
//
//                    mIsUnableToDrag = false;
//
//                }
//
//
//                if (DEBUG)
//
//                    Log.v(TAG, "Down at " + mLastMotionX + "," + mLastMotionY
//
//                            + " mIsBeingDragged=" + mIsBeingDragged
//
//                            + "mIsUnableToDrag=" + mIsUnableToDrag);
//
//                break;
//
//            }
//
//
//            case MotionEventCompat.ACTION_POINTER_UP:
//
//                onSecondaryPointerUp(ev);
//
//                break;
//
//        }
//
//
//
//        /*
//
//         * The only time we want to intercept motion events is if we are in the
//
//         * drag mode.
//
//         */
//
//        return mIsBeingDragged;
//
//    }
//
//
//    @Override
//
//    public boolean onTouchEvent(MotionEvent ev) {
//
//        if (mFakeDragging) {
//
//            // A fake drag is in progress already, ignore this real one
//
//            // but still eat the touch events.
//
//            // (It is likely that the user is multi-touching the screen.)
//
//            return true;
//
//        }
//
//
//        if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
//
//            // Don't handle edge touches immediately -- they may actually belong
//
//            // to one of our
//
//            // descendants.
//
//            return false;
//
//        }
//
//
//        if (mAdapter == null || mAdapter.getCount() == 0) {
//
//            // Nothing to present or scroll; nothing to touch.
//
//            return false;
//
//        }
//
//
//        if (mVelocityTracker == null) {
//
//            mVelocityTracker = VelocityTracker.obtain();
//
//        }
//
//        mVelocityTracker.addMovement(ev);
//
//
//        final int action = ev.getAction();
//
//        boolean needsInvalidate = false;
//
//
//        switch (action & MotionEventCompat.ACTION_MASK) {
//
//            case MotionEvent.ACTION_DOWN: {
//
//                /*
//
//                 * If being flinged and user touches, stop the fling. isFinished
//
//                 * will be false if being flinged.
//
//                 */
//
//                completeScroll();
//
//
//                // Remember where the motion event started
//
//                mLastMotionX = mInitialMotionX = ev.getX();
//
//                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
//
//                break;
//
//            }
//
//            case MotionEvent.ACTION_MOVE:
//
//                if (!mIsBeingDragged) {
//
//                    final int pointerIndex = MotionEventCompat.findPointerIndex(ev,
//
//                            mActivePointerId);
//
//                    final float x = MotionEventCompat.getX(ev, pointerIndex);
//
//                    final float xDiff = Math.abs(x - mLastMotionX);
//
//                    final float y = MotionEventCompat.getY(ev, pointerIndex);
//
//                    final float yDiff = Math.abs(y - mLastMotionY);
//
//                    if (DEBUG)
//
//                        Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff
//
//                                + "," + yDiff);
//
//                    if (xDiff > mTouchSlop && xDiff > yDiff) {
//
//                        if (DEBUG)
//
//                            Log.v(TAG, "Starting drag!");
//
//                        mIsBeingDragged = true;
//
//                        mLastMotionX = x;
//
//                        setScrollState(SCROLL_STATE_DRAGGING);
//
//                        setScrollingCacheEnabled(true);
//
//                    }
//
//                }
//
//                if (mIsBeingDragged) {
//
//                    // Scroll to follow the motion event
//
//                    final int activePointerIndex = MotionEventCompat
//
//                            .findPointerIndex(ev, mActivePointerId);
//
//                    final float x = MotionEventCompat.getX(ev, activePointerIndex);
//
//                    final float deltaX = mLastMotionX - x;
//
//                    mLastMotionX = x;
//
//                    float oldScrollX = getScrollX();
//
//                    float scrollX = oldScrollX + deltaX;
//
//                    final int width = getWidth();
//
//                    final int widthWithMargin = width + mPageMargin;
//
//
//                    final int lastItemIndex = mAdapter.getCount() - 1;
//
//                    final float leftBound = Math.max(0, (mCurItem - 1)
//
//                            * widthWithMargin);
//
//                    final float rightBound = Math.min(mCurItem + 1, lastItemIndex)
//
//                            * widthWithMargin;
//
//                    if (scrollX < leftBound) {
//
//                        if (leftBound == 0) {
//
//                            float over = -scrollX;
//
//                            needsInvalidate = mLeftEdge.onPull(over / width);
//
//                        }
//
//                        scrollX = leftBound;
//
//                    } else if (scrollX > rightBound) {
//
//                        if (rightBound == lastItemIndex * widthWithMargin) {
//
//                            float over = scrollX - rightBound;
//
//                            needsInvalidate = mRightEdge.onPull(over / width);
//
//                        }
//
//                        scrollX = rightBound;
//
//                    }
//
//                    // Don't lose the rounded component
//
//                    mLastMotionX += scrollX - (int) scrollX;
//
//                    scrollTo((int) scrollX, getScrollY());
//
//                    if (mOnPageChangeListener != null) {
//
//                        final int position = (int) scrollX / widthWithMargin;
//
//                        final int positionOffsetPixels = (int) scrollX
//
//                                % widthWithMargin;
//
//                        final float positionOffset = (float) positionOffsetPixels
//
//                                / widthWithMargin;
//
//                        mOnPageChangeListener.onPageScrolled(position,
//
//                                positionOffset, positionOffsetPixels);
//
//                    }
//
//                }
//
//                break;
//
//            case MotionEvent.ACTION_UP:
//
//                if (mIsBeingDragged) {
//
//                    final VelocityTracker velocityTracker = mVelocityTracker;
//
//                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
//
//                    int initialVelocity = (int) VelocityTrackerCompat.getXVelocity(
//
//                            velocityTracker, mActivePointerId);
//
//                    mPopulatePending = true;
//
//                    final int widthWithMargin = getWidth() + mPageMargin;
//
//                    final int scrollX = getScrollX();
//
//                    final int currentPage = scrollX / widthWithMargin;
//
//                    int nextPage = initialVelocity > 0 ? currentPage
//
//                            : currentPage + 1;
//
//                    setCurrentItemInternal(nextPage, true, true, initialVelocity);
//
//
//                    mActivePointerId = INVALID_POINTER;
//
//                    endDrag();
//
//                    needsInvalidate = mLeftEdge.onRelease()
//
//                            | mRightEdge.onRelease();
//
//                }
//
//                break;
//
//            case MotionEvent.ACTION_CANCEL:
//
//                if (mIsBeingDragged) {
//
//                    setCurrentItemInternal(mCurItem, true, true);
//
//                    mActivePointerId = INVALID_POINTER;
//
//                    endDrag();
//
//                    needsInvalidate = mLeftEdge.onRelease()
//
//                            | mRightEdge.onRelease();
//
//                }
//
//                break;
//
//            case MotionEventCompat.ACTION_POINTER_DOWN: {
//
//                final int index = MotionEventCompat.getActionIndex(ev);
//
//                final float x = MotionEventCompat.getX(ev, index);
//
//                mLastMotionX = x;
//
//                mActivePointerId = MotionEventCompat.getPointerId(ev, index);
//
//                break;
//
//            }
//
//            case MotionEventCompat.ACTION_POINTER_UP:
//
//                onSecondaryPointerUp(ev);
//
//                mLastMotionX = MotionEventCompat.getX(ev,
//
//                        MotionEventCompat.findPointerIndex(ev, mActivePointerId));
//
//                break;
//
//        }
//
//        if (needsInvalidate) {
//
//            invalidate();
//
//        }
//
//        return true;
//
//    }
//
//
//    @Override
//
//    public void draw(Canvas canvas) {
//
//        super.draw(canvas);
//
//        boolean needsInvalidate = false;
//
//
//        final int overScrollMode = ViewCompat.getOverScrollMode(this);
//
//        if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS
//
//                || (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS
//
//                && mAdapter != null && mAdapter.getCount() > 1)) {
//
//            if (!mLeftEdge.isFinished()) {
//
//                final int restoreCount = canvas.save();
//
//                final int height = getHeight() - getPaddingTop()
//
//                        - getPaddingBottom();
//
//
//                canvas.rotate(270);
//
//                canvas.translate(-height + getPaddingTop(), 0);
//
//                mLeftEdge.setSize(height, getWidth());
//
//                needsInvalidate |= mLeftEdge.draw(canvas);
//
//                canvas.restoreToCount(restoreCount);
//
//            }
//
//            if (!mRightEdge.isFinished()) {
//
//                final int restoreCount = canvas.save();
//
//                final int width = getWidth();
//
//                final int height = getHeight() - getPaddingTop()
//
//                        - getPaddingBottom();
//
//                final int itemCount = mAdapter != null ? mAdapter.getCount()
//
//                        : 1;
//
//
//                canvas.rotate(90);
//
//                canvas.translate(-getPaddingTop(), -itemCount
//
//                        * (width + mPageMargin) + mPageMargin);
//
//                mRightEdge.setSize(height, width);
//
//                needsInvalidate |= mRightEdge.draw(canvas);
//
//                canvas.restoreToCount(restoreCount);
//
//            }
//
//        } else {
//
//            mLeftEdge.finish();
//
//            mRightEdge.finish();
//
//        }
//
//
//        if (needsInvalidate) {
//
//            // Keep animating
//
//            invalidate();
//
//        }
//
//    }
//
//
//    @Override
//
//    protected void onDraw(Canvas canvas) {
//
//        super.onDraw(canvas);
//
//
//        // Draw the margin drawable if needed.
//
//        if (mPageMargin > 0 && mMarginDrawable != null) {
//
//            final int scrollX = getScrollX();
//
//            final int width = getWidth();
//
//            final int offset = scrollX % (width + mPageMargin);
//
//            if (offset != 0) {
//
//                // Pages fit completely when settled; we only need to draw when
//
//                // in between
//
//                final int left = scrollX - offset + width;
//
//                mMarginDrawable.setBounds(left, 0, left + mPageMargin,
//
//                        getHeight());
//
//                mMarginDrawable.draw(canvas);
//
//            }
//
//        }
//
//    }
//
//
//    /**
//     * Start a fake drag of the pager.
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * A fake drag can be useful if you want to synchronize the motion of the
//     * <p>
//     * ViewPager with the touch scrolling of another view, while still letting
//     * <p>
//     * the ViewPager control the snapping motion and fling behavior. (e.g.
//     * <p>
//     * parallax-scrolling tabs.) Call {@link #fakeDragBy(float)} to simulate the
//     * <p>
//     * actual drag motion. Call {@link #endFakeDrag()} to complete the fake drag
//     * <p>
//     * and fling as necessary.
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * <p>
//     * During a fake drag the ViewPager will ignore all touch events. If a real
//     * <p>
//     * drag is already in progress, this method will return false.
//     *
//     * @return true if the fake drag began successfully, false if it could not
//     * <p>
//     * be started.
//     * @see #fakeDragBy(float)
//     * @see #endFakeDrag()
//     */
//
//    public boolean beginFakeDrag() {
//
//        if (mIsBeingDragged) {
//
//            return false;
//
//        }
//
//        mFakeDragging = true;
//
//        setScrollState(SCROLL_STATE_DRAGGING);
//
//        mInitialMotionX = mLastMotionX = 0;
//
//        if (mVelocityTracker == null) {
//
//            mVelocityTracker = VelocityTracker.obtain();
//
//        } else {
//
//            mVelocityTracker.clear();
//
//        }
//
//        final long time = SystemClock.uptimeMillis();
//
//        final MotionEvent ev = MotionEvent.obtain(time, time,
//
//                MotionEvent.ACTION_DOWN, 0, 0, 0);
//
//        mVelocityTracker.addMovement(ev);
//
//        ev.recycle();
//
//        mFakeDragBeginTime = time;
//
//        return true;
//
//    }
//
//
//    /**
//     * End a fake drag of the pager.
//     *
//     * @see #beginFakeDrag()
//     * @see #fakeDragBy(float)
//     */
//
//    public void endFakeDrag() {
//
//        if (!mFakeDragging) {
//
//            throw new IllegalStateException(
//
//                    "No fake drag in progress. Call beginFakeDrag first.");
//
//        }
//
//
//        final VelocityTracker velocityTracker = mVelocityTracker;
//
//        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
//
//        int initialVelocity = (int) VelocityTrackerCompat.getYVelocity(
//
//                velocityTracker, mActivePointerId);
//
//        mPopulatePending = true;
//
//        if ((Math.abs(initialVelocity) > mMinimumVelocity)
//
//                || Math.abs(mInitialMotionX - mLastMotionX) >= (getWidth() / 3)) {
//
//            if (mLastMotionX > mInitialMotionX) {
//
//                setCurrentItemInternal(mCurItem - 1, true, true);
//
//            } else {
//
//                setCurrentItemInternal(mCurItem + 1, true, true);
//
//            }
//
//        } else {
//
//            setCurrentItemInternal(mCurItem, true, true);
//
//        }
//
//        endDrag();
//
//
//        mFakeDragging = false;
//
//    }
//
//
//    /**
//     * Fake drag by an offset in pixels. You must have called
//     * <p>
//     * {@link #beginFakeDrag()} first.
//     *
//     * @param xOffset Offset in pixels to drag by.
//     * @see #beginFakeDrag()
//     * @see #endFakeDrag()
//     */
//
//    public void fakeDragBy(float xOffset) {
//
//        if (!mFakeDragging) {
//
//            throw new IllegalStateException(
//
//                    "No fake drag in progress. Call beginFakeDrag first.");
//
//        }
//
//
//        mLastMotionX += xOffset;
//
//        float scrollX = getScrollX() - xOffset;
//
//        final int width = getWidth();
//
//        final int widthWithMargin = width + mPageMargin;
//
//
//        final float leftBound = Math.max(0, (mCurItem - 1) * widthWithMargin);
//
//        final float rightBound = Math
//
//                .min(mCurItem + 1, mAdapter.getCount() - 1) * widthWithMargin;
//
//        if (scrollX < leftBound) {
//
//            scrollX = leftBound;
//
//        } else if (scrollX > rightBound) {
//
//            scrollX = rightBound;
//
//        }
//
//        // Don't lose the rounded component
//
//        mLastMotionX += scrollX - (int) scrollX;
//
//        scrollTo((int) scrollX, getScrollY());
//
//        if (mOnPageChangeListener != null) {
//
//            final int position = (int) scrollX / widthWithMargin;
//
//            final int positionOffsetPixels = (int) scrollX % widthWithMargin;
//
//            final float positionOffset = (float) positionOffsetPixels
//
//                    / widthWithMargin;
//
//            mOnPageChangeListener.onPageScrolled(position, positionOffset,
//
//                    positionOffsetPixels);
//
//        }
//
//
//        // Synthesize an event for the VelocityTracker.
//
//        final long time = SystemClock.uptimeMillis();
//
//        final MotionEvent ev = MotionEvent.obtain(mFakeDragBeginTime, time,
//
//                MotionEvent.ACTION_MOVE, mLastMotionX, 0, 0);
//
//        mVelocityTracker.addMovement(ev);
//
//        ev.recycle();
//
//    }
//
//
//    /**
//     * Returns true if a fake drag is in progress.
//     *
//     * @return true if currently in a fake drag, false otherwise.
//     * @see #beginFakeDrag()
//     * @see #fakeDragBy(float)
//     * @see #endFakeDrag()
//     */
//
//    public boolean isFakeDragging() {
//
//        return mFakeDragging;
//
//    }
//
//
//    private void onSecondaryPointerUp(MotionEvent ev) {
//
//        final int pointerIndex = MotionEventCompat.getActionIndex(ev);
//
//        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
//
//        if (pointerId == mActivePointerId) {
//
//            // This was our active pointer going up. Choose a new
//
//            // active pointer and adjust accordingly.
//
//            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
//
//            mLastMotionX = MotionEventCompat.getX(ev, newPointerIndex);
//
//            mActivePointerId = MotionEventCompat.getPointerId(ev,
//
//                    newPointerIndex);
//
//            if (mVelocityTracker != null) {
//
//                mVelocityTracker.clear();
//
//            }
//
//        }
//
//    }
//
//
//    private void endDrag() {
//
//        mIsBeingDragged = false;
//
//        mIsUnableToDrag = false;
//
//
//        if (mVelocityTracker != null) {
//
//            mVelocityTracker.recycle();
//
//            mVelocityTracker = null;
//
//        }
//
//    }
//
//
//    private void setScrollingCacheEnabled(boolean enabled) {
//
//        if (mScrollingCacheEnabled != enabled) {
//
//            mScrollingCacheEnabled = enabled;
//
//            if (USE_CACHE) {
//
//                final int size = getChildCount();
//
//                for (int i = 0; i < size; ++i) {
//
//                    final View child = getChildAt(i);
//
//                    if (child.getVisibility() != GONE) {
//
//                        child.setDrawingCacheEnabled(enabled);
//
//                    }
//
//                }
//
//            }
//
//        }
//
//    }
//
//
//    /**
//     * Tests scrollability within child views of v given a delta of dx.
//     *
//     * @param v      View to test for horizontal scrollability
//     * @param checkV Whether the view v passed should itself be checked for
//     *               <p>
//     *               scrollability (true), or just its children (false).
//     * @param dx     Delta scrolled in pixels
//     * @param x      X coordinate of the active touch point
//     * @param y      Y coordinate of the active touch point
//     * @return true if child views of v can be scrolled by delta of dx.
//     */
//
//    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
//
//        if (v instanceof ViewGroup) {
//
//            final ViewGroup group = (ViewGroup) v;
//
//            final int scrollX = v.getScrollX();
//
//            final int scrollY = v.getScrollY();
//
//            final int count = group.getChildCount();
//
//            // Count backwards - let topmost views consume scroll distance
//
//            // first.
//
//            for (int i = count - 1; i >= 0; i--) {
//
//                // TODO: Add versioned support here for transformed views.
//
//                // This will not work for transformed views in Honeycomb+
//
//                final View child = group.getChildAt(i);
//
//                if (x + scrollX >= child.getLeft()
//
//                        && x + scrollX < child.getRight()
//
//                        && y + scrollY >= child.getTop()
//
//                        && y + scrollY < child.getBottom()
//
//                        && canScroll(child, true, dx,
//
//                        x + scrollX - child.getLeft(), y + scrollY
//
//                                - child.getTop())) {
//
//                    return true;
//
//                }
//
//            }
//
//        }
//
//
//        return checkV && ViewCompat.canScrollHorizontally(v, -dx);
//
//    }
//
//
//    @Override
//
//    public boolean dispatchKeyEvent(KeyEvent event) {
//
//        // Let the focused view and/or our descendants get the key first
//
//        return super.dispatchKeyEvent(event) || executeKeyEvent(event);
//
//    }
//
//
//    /**
//     * You can call this function yourself to have the scroll view perform
//     * <p>
//     * scrolling from a key event, just as if the event had been dispatched to
//     * <p>
//     * it by the view hierarchy.
//     *
//     * @param event The key event to execute.
//     * @return Return true if the event was handled, else false.
//     */
//
//    public boolean executeKeyEvent(KeyEvent event) {
//
//        boolean handled = false;
//
//        if (event.getAction() == KeyEvent.ACTION_DOWN) {
//
//            switch (event.getKeyCode()) {
//
//                case KeyEvent.KEYCODE_DPAD_LEFT:
//
//                    handled = arrowScroll(FOCUS_LEFT);
//
//                    break;
//
//                case KeyEvent.KEYCODE_DPAD_RIGHT:
//
//                    handled = arrowScroll(FOCUS_RIGHT);
//
//                    break;
//
//                case KeyEvent.KEYCODE_TAB:
//
//                    if (KeyEventCompat.hasNoModifiers(event)) {
//
//                        handled = arrowScroll(FOCUS_FORWARD);
//
//                    } else if (KeyEventCompat.hasModifiers(event,
//
//                            KeyEvent.META_SHIFT_ON)) {
//
//                        handled = arrowScroll(FOCUS_BACKWARD);
//
//                    }
//
//                    break;
//
//            }
//
//        }
//
//        return handled;
//
//    }
//
//
//    public boolean arrowScroll(int direction) {
//
//        View currentFocused = findFocus();
//
//        if (currentFocused == this)
//
//            currentFocused = null;
//
//
//        boolean handled = false;
//
//
//        View nextFocused = FocusFinder.getInstance().findNextFocus(this,
//
//                currentFocused, direction);
//
//        if (nextFocused != null && nextFocused != currentFocused) {
//
//            if (direction == View.FOCUS_LEFT) {
//
//                // If there is nothing to the left, or this is causing us to
//
//                // jump to the right, then what we really want to do is page
//
//                // left.
//
//                if (currentFocused != null
//
//                        && nextFocused.getLeft() >= currentFocused.getLeft()) {
//
//                    handled = pageLeft();
//
//                } else {
//
//                    handled = nextFocused.requestFocus();
//
//                }
//
//            } else if (direction == View.FOCUS_RIGHT) {
//
//                // If there is nothing to the right, or this is causing us to
//
//                // jump to the left, then what we really want to do is page
//
//                // right.
//
//                if (currentFocused != null
//
//                        && nextFocused.getLeft() <= currentFocused.getLeft()) {
//
//                    handled = pageRight();
//
//                } else {
//
//                    handled = nextFocused.requestFocus();
//
//                }
//
//            }
//
//        } else if (direction == FOCUS_LEFT || direction == FOCUS_BACKWARD) {
//
//            // Trying to move left and nothing there; try to page.
//
//            handled = pageLeft();
//
//        } else if (direction == FOCUS_RIGHT || direction == FOCUS_FORWARD) {
//
//            // Trying to move right and nothing there; try to page.
//
//            handled = pageRight();
//
//        }
//
//        if (handled) {
//
//            playSoundEffect(SoundEffectConstants
//
//                    .getContantForFocusDirection(direction));
//
//        }
//
//        return handled;
//
//    }
//
//
//    boolean pageLeft() {
//
//        if (mCurItem > 0) {
//
//            setCurrentItem(mCurItem - 1, true);
//
//            return true;
//
//        }
//
//        return false;
//
//    }
//
//
//    boolean pageRight() {
//
//        if (mAdapter != null && mCurItem < (mAdapter.getCount() - 1)) {
//
//            setCurrentItem(mCurItem + 1, true);
//
//            return true;
//
//        }
//
//        return false;
//
//    }
//
//
//    /**
//     * We only want the current page that is being shown to be focusable.
//     */
//
//    @Override
//
//    public void addFocusables(ArrayList<View> views, int direction,
//
//                              int focusableMode) {
//
//        final int focusableCount = views.size();
//
//
//        final int descendantFocusability = getDescendantFocusability();
//
//
//        if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
//
//            for (int i = 0; i < getChildCount(); i++) {
//
//                final View child = getChildAt(i);
//
//                if (child.getVisibility() == VISIBLE) {
//
//                    ItemInfo ii = infoForChild(child);
//
//                    if (ii != null && ii.position == mCurItem) {
//
//                        child.addFocusables(views, direction, focusableMode);
//
//                    }
//
//                }
//
//            }
//
//        }
//
//
//        // we add ourselves (if focusable) in all cases except for when we are
//
//        // FOCUS_AFTER_DESCENDANTS and there are some descendants focusable.
//
//        // this is
//
//        // to avoid the focus search finding layouts when a more precise search
//
//        // among the focusable children would be more interesting.
//
//        if (descendantFocusability != FOCUS_AFTER_DESCENDANTS ||
//
//                // No focusable descendants
//
//                (focusableCount == views.size())) {
//
//            // Note that we can't call the superclass here, because it will
//
//            // add all views in. So we need to do the same thing View does.
//
//            if (!isFocusable()) {
//
//                return;
//
//            }
//
//            if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
//
//                    && isInTouchMode() && !isFocusableInTouchMode()) {
//
//                return;
//
//            }
//
//            if (views != null) {
//
//                views.add(this);
//
//            }
//
//        }
//
//    }
//
//
//    /**
//     * We only want the current page that is being shown to be touchable.
//     */
//
//    @Override
//
//    public void addTouchables(ArrayList<View> views) {
//
//        // Note that we don't call super.addTouchables(), which means that
//
//        // we don't call View.addTouchables(). This is okay because a ViewPager
//
//        // is itself not touchable.
//
//        for (int i = 0; i < getChildCount(); i++) {
//
//            final View child = getChildAt(i);
//
//            if (child.getVisibility() == VISIBLE) {
//
//                ItemInfo ii = infoForChild(child);
//
//                if (ii != null && ii.position == mCurItem) {
//
//                    child.addTouchables(views);
//
//                }
//
//            }
//
//        }
//
//    }
//
//
//    /**
//     * We only want the current page that is being shown to be focusable.
//     */
//
//    @Override
//
//    protected boolean onRequestFocusInDescendants(int direction,
//
//                                                  Rect previouslyFocusedRect) {
//
//        int index;
//
//        int increment;
//
//        int end;
//
//        int count = getChildCount();
//        if ((direction & FOCUS_FORWARD) != 0) {
//            index = 0;
//            increment = 1;
//            end = count;
//        } else {
//            index = count - 1;
//            increment = -1;
//            end = -1;
//        }
//        for (int i = index; i != end; i += increment) {
//            View child = getChildAt(i);
//            if (child.getVisibility() == VISIBLE) {
//                ItemInfo ii = infoForChild(child);
//                if (ii != null && ii.position == mCurItem) {
//                    if (child.requestFocus(direction, previouslyFocusedRect)) {
//                        return true;
//                    }
//                }
//            }
//        }
//        return false;
//    }
//
//    @Override
//    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
//        // ViewPagers should only report accessibility info for the current
//        // page,
//        // otherwise things get very confusing.
//        // TODO: Should this note something about the paging container?
//        final int childCount = getChildCount();
//        for (int i = 0; i < childCount; i++) {
//            final View child = getChildAt(i);
//            if (child.getVisibility() == VISIBLE) {
//                final ItemInfo ii = infoForChild(child);
//                if (ii != null && ii.position == mCurItem
//                        && child.dispatchPopulateAccessibilityEvent(event)) {
//                    return true;
//                }
//            }
//        }
//        return false;
//    }
//
//    private class PagerObserver extends DataSetObserver {
//        @Override
//        public void onChanged() {
//            dataSetChanged();
//        }
//
//        @Override
//        public void onInvalidated() {
//            dataSetChanged();
//        }
//    }
//}
